﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public struct NextStep
{
    public Chess Chess;
    public int Score;
    public Vector2Int MovePosition;
    public Vector2Int AttackPosition;
    
    public SoldierChessDateSO soldierChessDate;
}

public struct NextCardStep
{
    public Card Card;
    public int Score;
    public BuildingChessDateSO ChessDate;
    public Vector2Int Position;
}

public class HandleAI : MonoBehaviour
{
    public List<Chess> chessList;
    private Dictionary<Vector2Int, Lattice> latticeDic;
    private List<Card> handCardList;
    private List<Chess> playerChessList = new();
    private List<Chess> aiChessList = new();
    private Dictionary<Chess,HashSet<Vector2Int>> beAttackedPositions = new();

    public int minBuildingCount;
    public int chessCoefficientInField = 10;//场中棋子的系数,如果场中棋子的个数少,那么会增加出兵的计算系数
    public CardDeck cardDeck;

    private void Awake()
    {
        handCardList = cardDeck.player2HandCardList;
    }

    private void OnEnable()
    {
        EventCenter.GetInstance().AddEventListener("Player2TurnBegin",CalculateNextStep);
    }

    private void OnDisable()
    {
        EventCenter.GetInstance().RemoveEventListener("Player2TurnBegin",CalculateNextStep);
    }

    private void CalculateNextStep()
    {
        print(nameof(CalculateNextStep));
        StartCoroutine(ReallyCalculateNextStep());  
    }
    
    int buildingCount = 0;
    int soliderCount = 0;

    private IEnumerator ReallyCalculateNextStep()
    {
        yield return new WaitForSeconds(5f);
        UpdateChessList();
        buildingCount = 0;
        soliderCount = 0;
        
        foreach (var chess in aiChessList)
        {
            if(chess.ChessDetail.ChessType == ChessType.Building) 
                buildingCount++;
            else
                soliderCount++;
            
        }
        
        //执行出牌的判断
        NextCardStep nextCardStep = GetCardScore();
        
        //执行兵的移动的判断
        var bestNextStep = GetChessScore();
        print(nextCardStep.Score);
        print(bestNextStep.Score);
        if (bestNextStep.Score > nextCardStep.Score && bestNextStep.Score != -999)
        {
            EventCenter.GetInstance().EventTrigger("AIOperation",bestNextStep);
        }
        else if(bestNextStep.Score <= nextCardStep.Score && nextCardStep.Score != -999)
        {
            nextCardStep.Card.UseCard(nextCardStep.Position);
        }
        
        EventCenter.GetInstance().EventTrigger("Player2TurnEnd");
        
    }

    private void UpdateChessList()
    {
        chessList = ChessManager.GetInstance().chessList;
        latticeDic = ChessBoardMgr.GetInstance().ChessboardDict;
        
        playerChessList.Clear();
        aiChessList.Clear();
        
        
        foreach (var chess in chessList)
        {
            if (chess.ChessDetail.Side == ChessSide.Player1)
            {
                playerChessList.Add(chess);
            }
            else
            {
                aiChessList.Add(chess);
            }
        }
        GetAttackPositions();
    }
    
    
    private NextStep GetChessScore()
    {
        
        var bestNextStep = new NextStep
        {
            Score = -999
        };
        if (aiChessList.Count == 0)
        {
            bestNextStep.Chess = null;
            return bestNextStep;
        }
        else
        {
            bestNextStep.Chess = aiChessList[0];
        }
        
        foreach (var chess in aiChessList)
        {
            var date = latticeDic[chess.ChessDetail.Position].chessDate;
            var c = latticeDic[chess.ChessDetail.Position].chess;
            
            //找出可以移动的格子
            if (!(date.moveRange.vector2IntMode.Count == 1 && date.moveRange.vector2IntMode[0] == Vector2Int.zero) && c.ChessDetail.CanMove == true &&  c.ChessDetail.CanUse == true)
            {
                var temp = Math.GetEnemyTargetPosition(chess.ChessDetail.Position, date.moveRange.vector2IntMode);
                foreach (var movePosition in date.moveRange.rangeType == RangeType.Normal ? 
                             Math.GetEnemyTargetPosition(chess.ChessDetail.Position,date.moveRange.vector2IntMode)
                             : date.moveRange.vector2IntMode)
                {
                    if (latticeDic[movePosition].chessDate) continue;
                    int score = 0;
                    //找出可以攻击的棋子
                    var list = date.attackRange.rangeType == RangeType.Normal ?
                                 Math.GetEnemyTargetPosition(movePosition, date.attackRange.vector2IntMode)
                                 : date.attackRange.vector2IntMode;
                    foreach (var attackPosition in list)
                    {
                        var targetLattice = latticeDic[attackPosition];
                        if (targetLattice.chess
                            && targetLattice.chess.GetChessSide() != ChessSide.Player2)
                        {
                            //加上攻击目标的得分
                            score = GetScoreByPositionY(movePosition) + targetLattice.chessDate.score;
                    
                            
                        }else if(!targetLattice.chess)
                        {
                            //仅移动不攻击
                            score = GetScoreByPositionY(movePosition);
                        }
                        
                        //减去被攻击的得分
                        foreach (var playerChess in playerChessList)
                        {
                            if(playerChess.ChessDetail.Position == attackPosition || playerChess.chessDate.chessType == ChessType.Building) continue;
                            var playerDate = latticeDic[playerChess.ChessDetail.Position].chessDate as SoldierChessDateSO;
                            //如果不在这个棋子的攻击范围内跳过继续遍历
                            if (!beAttackedPositions[playerChess].Contains(movePosition)) continue;
                            //在不是攻击目标的攻击范围中
                            if(playerDate?.attack<date.health)
                            {
                                score -= playerDate.attackScore;
                                continue;
                            }
                            else
                            {
                                score -= playerDate.killScore;
                                break;
                            }
                        }
                        print(chess.chessDate.name + "得分是" + score +
                            "\n位置于" + bestNextStep.Chess.ChessDetail.Position + 
                            "\n想要移动的位置:" + movePosition + 
                            "\n想要攻击的位置" + attackPosition);
                        //判断哪个分值最大
                        if (bestNextStep.Score >= score) continue;
                        bestNextStep.Score = score;
                        bestNextStep.Chess = chess;
                        bestNextStep.MovePosition = movePosition;
                        bestNextStep.AttackPosition = !latticeDic[attackPosition].chess ? movePosition : attackPosition;
                    }
                    if(list.Count == 0)
                    {
                        score = GetScoreByPositionY(movePosition);
                        print(chess.chessDate.name + "得分是" + score +
                            "\n位置于" + bestNextStep.Chess.ChessDetail.Position +
                            "\n想要移动的位置:" + movePosition +
                            "\n想要攻击的位置" + movePosition);
                        //判断哪个分值最大
                        if (bestNextStep.Score >= score) continue;
                        bestNextStep.Score = score;
                        bestNextStep.Chess = chess;
                        bestNextStep.MovePosition = movePosition;
                        bestNextStep.AttackPosition = movePosition;
                    }
                }
            }
            else
            {
                if (date.chessType == ChessType.Building)
                {
                    var buildingDate = date as BuildingChessDateSO;
                    //建筑出兵
                    foreach (var chessDate in buildingDate.soldierChessDates)
                    {
                        if (chessDate.resourcesPoint > PlayerResourcesManager.GetInstance().Player2Resources || 
                            latticeDic[chess.ChessDetail.Position-Vector2Int.up].chessDate)
                        {
                            continue;
                        }
                        
                        var score = chessDate.score + chessCoefficientInField - 2 *(aiChessList.Count - buildingCount);
                        var position = chess.ChessDetail.Position - Vector2Int.up;
                        //减去被攻击的得分
                        foreach (var playerChess in playerChessList)
                        {
                            var playerDate = latticeDic[playerChess.ChessDetail.Position].chessDate as SoldierChessDateSO;
                            if (!beAttackedPositions[playerChess].Contains(position)) continue;
                            //在攻击范围中
                            if(playerDate.attack<chessDate.health)
                            {
                                score -= playerDate.attackScore * 2;
                                continue;
                            }
                            else
                            {
                                score -= playerDate.killScore * 2;
                                break;
                            }
                        }

                        print(chess.chessDate.name + "得分是" + score +
                            "\n位置于" + chess.ChessDetail.Position +
                            "\n想要出的兵是" + chessDate.chessName +
                            "\n想要移动的位置:" + position);

                        //判断哪个分值最大
                        if (bestNextStep.Score >= score) continue;
                        bestNextStep.Score = score;
                        bestNextStep.Chess = chess;
                        bestNextStep.soldierChessDate = chessDate;
                        bestNextStep.MovePosition = position;
                        bestNextStep.AttackPosition = position;
                    }
                }
                else if ((date.moveRange.vector2IntMode.Count == 1 && date.moveRange.vector2IntMode[0] == Vector2Int.zero) || (chess.ChessDetail.CanMove == false && chess.ChessDetail.CanUse))
                {
                    //不能移动的棋子但能够攻击的棋子
                    foreach (var attackPosition in date.attackRange.rangeType == RangeType.Normal
                                 ? Math.GetEnemyTargetPosition(chess.ChessDetail.Position, date.attackRange.vector2IntMode)
                                 : date.attackRange.vector2IntMode)
                    {
                        int score = 0;
                        var targetLattice = latticeDic[attackPosition];
                        if (targetLattice.chess
                            && targetLattice.chess.GetChessSide() != ChessSide.Player2)
                        {
                            //加上攻击目标的得分
                            score = targetLattice.chessDate.score;
                        }
                        print(chess + "得分是" + score +
                            "\n位置于" + chess.ChessDetail.Position +
                            "\n想要移动的位置:" + chess.ChessDetail.Position +
                            "\n想要攻击的位置" + attackPosition);


                        //判断哪个分值最大
                        if (bestNextStep.Score >= score) continue;
                        bestNextStep.Score = score;
                        bestNextStep.Chess = chess;
                        bestNextStep.MovePosition = chess.ChessDetail.Position;
                        bestNextStep.AttackPosition = attackPosition;
                    }
                }
            }
        }
        
        return bestNextStep;
    }

    private NextCardStep GetCardScore()
    {
        var bestNextStep = new NextCardStep()
        {
            Card = null,
            Score = -999,
        };
        if(handCardList.Count == 0) return bestNextStep;
        
        foreach (var card in handCardList)
        {
            if (card.buildingDate.resourcesPoint > PlayerResourcesManager.GetInstance().Player2Resources)
            {
                continue;
            }
            
            foreach (var movePosition in card.buildingDate.canPlacedLattices.vector2IntMode)
            {
                var reallyPosition = FlipVector(movePosition);
                if(latticeDic[reallyPosition].chessDate) continue;
                var score = card.buildingDate.score;
                score += GetScoreByPositionX(reallyPosition);
                score += (int)Calculate(buildingCount);
                    
                //减去被攻击的得分
                foreach (var playerChess in playerChessList)
                {
                    if(latticeDic[playerChess.ChessDetail.Position].chessDate.chessType != ChessType.Soldier) continue;
                    var playerDate = latticeDic[playerChess.ChessDetail.Position].chessDate as SoldierChessDateSO;
                    if (!beAttackedPositions.ContainsKey(playerChess))
                    {
                        print(playerChess.ChessDetail.Position);
                        print(playerChess.chessDate.name);
                    }
                    if (!beAttackedPositions[playerChess].Contains(reallyPosition)) continue;
                    //在攻击范围中
                    if(playerDate!.attack<card.buildingDate.health)
                    {
                        score -= playerDate.attackScore * 2;
                        continue;
                    }
                    else
                    {
                        score -= playerDate.killScore * 2;
                        break;
                    }
                }
                print(card.buildingDate.chessName + "得分是" + score +
                            "\n位置于" + reallyPosition);

                if (bestNextStep.Score >= score) continue;
                bestNextStep.Score = score;
                bestNextStep.Card = card;
                bestNextStep.ChessDate = card.buildingDate;
                bestNextStep.Position = reallyPosition;
            }
        }
        
        
        return bestNextStep;
    }

    private int GetScoreByPositionY(Vector2Int position)
    {
        return position.y switch
        {
            7 => 7,
            6 => 10,
            5 => 12,
            4 => 15,
            3 => 18,
            2 => 20,
            1 => 25,
            0 => 30,
            _ => 0
        };
    }

    private int GetScoreByPositionX(Vector2Int position)
    {
        return position.x switch
        {
            7 or 0 => 2,
            6 or 1 => 4,
            5 or 2 => 6,
            4 or 3 => 8,
            _ => 0
        };
    }


    private void GetAttackPositions()
    {
        beAttackedPositions.Clear();
        
        foreach (var playerChess in playerChessList)
        {
            var initialPos = playerChess.ChessDetail.Position;
            var playerDate = latticeDic[playerChess.ChessDetail.Position].chessDate;
            var validPositions = new List<Vector2Int>();
            foreach (var displacement in playerDate.moveRange.vector2IntMode)
            {
                var newPos = initialPos + displacement;
                if (newPos.x is >= 0 and < 8 && newPos.y is >= 0 and < 8)
                {
                    validPositions.Add(newPos);
                }
            }
            HashSet<Vector2Int> attackPositions = new HashSet<Vector2Int>();
            foreach (var validPos in validPositions)
            {
                foreach (var attack in playerDate.attackRange.vector2IntMode)
                {
                    var attackPos = playerDate.attackRange.rangeType == RangeType.Normal
                        ? validPos + attack
                        : attack;
                    if (attackPos.x is >= 0 and < 8 && attackPos.y is >= 0 and < 8)
                    {
                        attackPositions.Add(attackPos);
                    }
                }
            }
            beAttackedPositions.Add(playerChess,attackPositions);
        }
    }
    
    
    
    public static Vector2Int FlipVector(Vector2Int input)
    {
        // 计算翻转后的坐标
        int flippedX = 7 - input.x;
        int flippedY = 7 - input.y;

        // 返回翻转后的结果
        return new Vector2Int(flippedX, flippedY);
    }
    
    public int _a = 2;
    public double Calculate(int b)
    {
        if (b < _a)
        {
            // 当b小于a时，结果随b减小线性增大
            return (_a - b + 2);
        }
        else
        {
            // 当b大于等于a时，结果随b增大反比例减小
            return 1.0 / (b - _a + 2);
        }
    }
}


